#!/bin/sh

# Copyright (c)2003 Brian Manning
# brian (at) antlinux dot com

# System bootstrapping script.  This script will boot the system, mount the
# root partition from an LVM volume, then transfer control to the /sbin/init
# binary found on that freshly-mounted filesystem

# some good references:
# /usr/src/linux/Documentation/initrd.txt
# http://pingu.salk.edu/LDP/HOWTO/LVM-HOWTO/index.html
# http://pingu.salk.edu/LDP/HOWTO/Bootdisk-HOWTO/index.html
# http://pingu.salk.edu/LDP/HOWTO/Boot+Root+Raid+LILO.html
#
# http://www.antlinux.com/pmwiki/pmwiki.php?n=AntLinux.BootFloppyBuildNotes

# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA  02111-1307 USA

# begin busybox setup; from here on down, you need to use the full path to
# busybox, along with the name of the module you want to run, as the busybox
# symlinks don't exist (yet)

# source the functions script.  this is where colorize() is coming from
. /etc/ant_functions.sh

# <create the root device too>
/bin/busybox makedevs -d /etc/devs.txt /

# you must pause before changing the font, otherwise you'll loose the output
# from the kernel booting
if /bin/busybox test $DEBUG -gt 0; then
    /bin/busybox echo "= DEBUG environment variable exists and is non-zero;"
    /bin/busybox echo "= Boot process is paused so boot output can be viewed"
    /bin/busybox echo "  Current PID is ${$}"
    /bin/busybox echo -n "  Press ${START}${BOLD};${F_GRN};${B_BLK}${END}"
    /bin/busybox echo -n "<Enter>${START};${NONE}${END} to continue: "
    # read is a shell built-in
    read ANSWER
fi

/bin/busybox clear
/bin/busybox echo -n "${START}${INFO}${END}=== Begin antlinux rcS script ==="
/bin/busybox echo "${START};${NONE}${END}"

# purdy font
/bin/busybox echo -n "${START}${TIP}${END}- Loading 'lode-lat1u-16' font "
/bin/busybox echo "from GoboLinux${START};${NONE}${END}" 
/bin/busybox gunzip -c /etc/lode-lat1u-16.psf.gz | /bin/busybox loadfont

# proc needs to be mounted before you can remount the root filesystem
# since the root filesystem is read-only at this point, when you mount /proc,
# the kernel goes to update /etc/mtab and fails (read-only filesystem)
/bin/busybox echo -n "${START}${TIP}${END}- Mounting /proc"
/bin/busybox echo "${START};${NONE}${END}"
/bin/busybox mount proc /proc -t proc 

/bin/busybox echo -n "${START}${TIP}${END}- Remounting root filesystem "
/bin/busybox echo "read/write${START};${NONE}${END}" 
/bin/busybox mount rootfs / -o remount,rw

/bin/busybox echo -n "${START}${TIP}${END}- Running busybox --install -s"
/bin/busybox echo "${START};${NONE}${END}"
/bin/busybox --install -s

# everything past this point doesn't need the busybox path anymore

cmd_status () {
    # check the status of the last run command; run a shell if it's anything
    # but 0
    STATUS=$1
    if [ $STATUS -ne 0 ]; then
        colorize "${FAILURE}" "Previous command failed with"
        colorize $INFO " status code: ${STATUS}"; echo
        DEBUG=1
        want_shell
    fi
} # cmd_status

want_shell () {
    # run a shell (only if $DEBUG is set)
    if [ "${DEBUG}" -a "${DEBUG}" -gt 0 ]; then
        colorize $INFO "Execute debug shell? [Y/n] "
        read ANSWER
        if [ "${ANSWER}" = "y" -o "${ANSWER}" = "Y" ]; then
            echo; echo
            colorize "${SUCCESS}" "Running /bin/sh (NetBSD ash Shell)"; echo
            exec /bin/sh 
            exit 1 # shouldn't get here
        fi # if [ "${ANSWER}" = "y" -o "${ANSWER}" = "Y" ];
    fi # if [ $DEBUG -gt 0 ];
} # want_shell()

# modules directory
#colorize $TIP "- Creating directory for mounting modules package"; echo
#/bin/mkdir -p /lib/modules/`uname -r`

colorize $TIP "- Determining Linux Kernel Version Number"; echo
# run uname, cut off everything after the '-' dash character
KERNEL_VER_STRING=`/bin/uname -r | /usr/bin/cut -d'-' -f 1`
# find the major version with cut
KERNEL_VERSION=`/bin/echo $KERNEL_VER_STRING | /usr/bin/cut -d'.' -f 1`
# find the patchlevel with cut
KERNEL_PATCHLEVEL=`/bin/echo $KERNEL_VER_STRING | /usr/bin/cut -d'.' -f 2`
# find the sublevel with cut
KERNEL_SUBLEVEL=`/bin/echo $KERNEL_VER_STRING | /usr/bin/cut -d'.' -f 3`

if [ $KERNEL_VERSION -eq 2 ]; then
    if [ $KERNEL_PATCHLEVEL -ge 6 ]; then
        colorize $INFO "  * Kernel 2.6 is running";echo
        colorize $INFO "  * Mounting sysfs (for 2.6 kernels)"; echo
        /bin/mount sysfs /sys -t sysfs 2>>/var/log/boot.log
        cmd_status $?
    else
        colorize $INFO "  * Kernel 2.4 is running, skipping sysfs mounting"
        echo
    fi
fi

# test to see if the modules cramfile was included in the initrd image.  
# yes - then mount the cramfile from the initrd image
# no - does a modules file exist on the compactflash card?
# 	yes - mount the modules cramfile from the compact flash card
# 	no - error out and report missing modules file
colorize $TIP "- Loading Kernel Modules"; echo
for MODULE in $(cat /etc/modules | grep -v "^#"); do
    colorize $TIP "  - loading ${MODULE}"; echo
    /sbin/modprobe ${MODULE}
    cmd_status $?
done

# Get the root volume name from the kernel command line. In order for
# this to work correctly, "root=/dev/vg0/Root_Volume_Name" needs to be passed 
# to the kernel command line (where Root_Volume_Name is replaced by your actual
# root volume's name. See the section about "Configuring Your Boot-Loader" in
# the INSTALL file in the EVMS package.
for name in `cat /proc/cmdline`; do
    echo $name | grep '^realroot=' > /dev/null
    if [ $? -eq 0 ]; then
        ROOT_VOL=`expr "$name" : '.*=\(.*\)'`
        break
    fi
done



want_shell

# Activate lvm volumes.
colorize $TIP "- Running vgscan"; echo
/sbin/vgscan
cmd_status $?

colorize $TIP "- Running vgchange on volume group zero (vg0)"; echo
/sbin/vgchange -ay --ignorelockingfailure vg0
cmd_status $?

if [ -n "$ROOT_VOL" ]; then
    # Get the device number for the root volume and set the
    # kernel's root-device.
    colorize $TIP "- Mounting root device ${ROOT_VOL} read-only"; echo
    mount -t auto -o ro $ROOT_VOL /mnt
    cmd_status $?
else
    # Don't have the root volume name - drop to a shell
    colorize $INFO "- Root volume not passed on the kernel command line"
    colorize $INFO "- Prompting for a shell"
    echo
    DEBUG=1
    want_shell
fi

if [ $KERNEL_VERSION -eq 2 ]; then
    if [ $KERNEL_PATCHLEVEL -ge 6 ]; then
        colorize $INFO "  * Unmounting sysfs (for 2.6 kernels)"; echo
        /bin/umount /sys
        cmd_status $?
    fi # if [ $KERNEL_PATCHLEVEL -ge 6 ];
fi # if [ $KERNEL_VERSION -eq 2 ];

want_shell

# unmount proc, it will get re-mounted later on 
colorize $INFO "  * Unmounting /proc"; echo
/bin/umount /proc
cmd_status $?

want_shell

colorize $INFO "=== End antlinux rcS script ==="; echo
colorize $INFO "=== Starting init on ${ROOT_VOL} ==="; echo

colorize $INFO " * Changing root directory with pivot_root"; echo
cd /mnt
# pivot_root takes $PWD and mounts it as /, moving the old root to $2

pivot_root . initrd 
if [ $? -gt 0 ]; then
    colorize "${FAILURE}" "pivot_root failed!"; echo
    DEBUG=1
    want_shell
fi

# need the gymnastics below so /sbin/init inherits a PID of 1; if init starts
# with a different PID, it will think you're trying to change the runlevel of
# an existing init process, and exit
colorize $INFO " * exec'ing /sbin/init..."; echo
exec chroot . /sbin/init $* < dev/console > dev/console 2>&1
